package Dao.PostgreSql;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;

import Dao.GenericDao;
import Entity.Cliente;
import Entity.Situacao;
import Entity.Titulo;
import Interface.InterfaceDao;

public class TituloPostgreSqlDao extends GenericDao implements InterfaceDao {

	public List<Object> findVencimentos(int dias) {
		List<Object> lista = new ArrayList<Object>();
		try {
			DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
			java.util.Date date = new java.util.Date();

			GregorianCalendar gc = new GregorianCalendar();
			gc.setTime(date);
			gc.add(gc.DAY_OF_MONTH, -dias);
			date = gc.getTime();

			// cria o objeto de conexao
			Connection conn = conexao();

			// monta o sql de insert
			String query = "";
			query += "with origem as ( \n";
			query += "   select \n";
			query += "      t.id, \n";
			query += "      t.\"dataVencimento\", \n";
			query += "      coalesce(t.\"valorDebito\", 0) as valorDebito, \n";
			query += "      coalesce(sum(s.\"valorPago\"), 0) as valorPago, \n";
			query += "      c.id as idCliente, \n";
			query += "      c.nome as nomeCliente, \n";
			query += "      c.email, \n";
			query += "      c.aviso \n";
			query += "   from titulo t \n";
			query += "   left join quitacao s on(s.id = t.\"idSituacao\") \n";
			query += "   inner join cliente c on(c.id = t.\"idCliente\") \n";
			query += "   where \n";
			query += "      '" + dateFormat.format(date)
					+ "' >  t.\"dataVencimento\" \n";
			query += "   group by t.id, t.\"dataVencimento\", t.\"valorDebito\", idCliente, nomeCliente, c.email, c.aviso \n";
			query += ") \n";
			query += "select * from origem o \n";
			query += "where o.\"valorpago\" < o.\"valordebito\"";

			// cria os parametros a serem passados no insert
			PreparedStatement preparedStmt = conn.prepareStatement(query);

			// executa o sql
			ResultSet q = preparedStmt.executeQuery();

			Titulo f;
			while (q.next()) {
				f = new Titulo();
				f.setId(q.getInt("id"));
				f.setDataVencimento(q.getDate("dataVencimento"));
				f.setValorDebito(q.getDouble("valorDebito"));
				f.setValorPago(q.getDouble("valorPago"));

				Cliente c = new Cliente();
				c.setId(q.getInt("idCliente"));
				c.setNome(q.getString("nomeCliente"));
				c.setEmail(q.getString("email"));
				c.setAviso(q.getInt("aviso"));
				f.setCliente(c);

				lista.add(f);
			}

			conn.close();
		} catch (Exception e) {
			System.err.println("Ocorreu um erro ao consultar todos!");
			System.err.println(e.getMessage());
		}
		return lista;
	}

	public List<Object> findVencimentosMes() {
		List<Object> lista = new ArrayList<Object>();
		try {
			DateFormat dateFormat = new SimpleDateFormat("yyyy");
			java.util.Date date = new java.util.Date();
			
			// cria o objeto de conexao
			Connection conn = conexao();

			// monta o sql de insert
			String query = "";
			query += "with origem as (  \n";
			query += "   select \n";
			query += "      t.id, \n";
			query += "      t.\"dataVencimento\", \n";
			query += "      coalesce(t.\"valorDebito\", 0) as valorDebito, \n";
			query += "      coalesce(sum(s.\"valorPago\"), 0) as valorPago \n";
			query += "   from titulo t  \n";
			query += "   left join quitacao s on(s.\"idTitulo\" = t.\"id\") \n";
			query += "   inner join cliente c on(c.id = t.\"idCliente\") \n";
			query += "   where \n";
			query += "      t.\"dataVencimento\" between '01/01/"+dateFormat.format(date) +"' and '30/12/"+dateFormat.format(date)+"' \n";
			query += "   group by t.id, t.\"dataVencimento\", t.\"valorDebito\" \n";
			query += ")  \n";
			query += "select \n";
			query += "   distinct \n";
			query += "   to_char(o.\"dataVencimento\", 'MM/yyyy') as data, \n";
			query += "   (sum(o.\"valordebito\") - sum(o.\"valorpago\")) as valorPagar \n";
			query += "from origem o \n";
			query += "where o.\"valorpago\" < o.\"valordebito\" \n";
			query += "group by data \n";

			// cria os parametros a serem passados no insert
			PreparedStatement preparedStmt = conn.prepareStatement(query);

			// executa o sql
			ResultSet q = preparedStmt.executeQuery();

			Titulo f;
			while (q.next()) {
				f = new Titulo();
				f.setDataRelatorio(q.getString("data"));
				f.setValorPagarRelatorio(q.getDouble("valorPagar"));
				lista.add(f);
			}

			conn.close();
		} catch (Exception e) {
			System.err.println("Ocorreu um erro ao consultar todos!");
			System.err.println(e.getMessage());
		}
		return lista;
	}

	@Override
	public List<Object> findAll() {
		List<Object> lista = new ArrayList<Object>();
		try {
			// cria o objeto de conexao
			Connection conn = conexao();

			// monta o sql de insert
			String query = "select \n";
			query += "t.*, \n";
			query += "s.descricao as descricaoSituacao, \n";
			query += "c.nome as nomeCliente \n";
			query += "from titulo t \n";
			query += "inner join situacao s on(s.id = t.\"idSituacao\") \n";
			query += "inner join cliente c on(c.id = t.\"idCliente\") \n";

			// cria os parametros a serem passados no insert
			PreparedStatement preparedStmt = conn.prepareStatement(query);

			// executa o sql
			ResultSet q = preparedStmt.executeQuery();

			Titulo f;
			while (q.next()) {
				f = new Titulo();
				f.setId(q.getInt("id"));
				Situacao s = new Situacao();
				s.setId(q.getInt("idSituacao"));
				s.setDescricao(q.getString("descricaoSituacao"));
				f.setSituacao(s);
				Cliente c = new Cliente();
				c.setId(q.getInt("idCliente"));
				c.setNome(q.getString("nomeCliente"));
				f.setCliente(c);
				f.setDataCadastro(q.getDate("dataCadastro"));
				f.setDataVencimento(q.getDate("dataVencimento"));
				f.setValorDebito(q.getDouble("valorDebito"));
				f.setJuroMes(q.getDouble("juroMes"));
				f.setJuro(q.getDouble("juro"));

				lista.add(f);
			}

			conn.close();
		} catch (Exception e) {
			System.err.println("Ocorreu um erro ao consultar todos!");
			System.err.println(e.getMessage());
		}
		return lista;
	}

	@Override
	public void insert(Object obj) {
		try {
			Titulo objF = (Titulo) obj;
			// cria o objeto de conexao
			Connection conn = conexao();

			// monta o sql de insert
			String query = " insert into Titulo values (default, ?,?,?,?,?,?,?)";

			// cria os parametros a serem passados no insert
			PreparedStatement preparedStmt = conn.prepareStatement(query);
			preparedStmt.setInt(1, objF.getSituacao().getId());
			preparedStmt.setInt(2, objF.getCliente().getId());
			preparedStmt.setDate(3, new Date(objF.getDataCadastro().getTime()));
			preparedStmt.setDate(4,
					new Date(objF.getDataVencimento().getTime()));
			preparedStmt.setDouble(5, objF.getValorDebito());
			preparedStmt.setDouble(6, objF.getJuroMes());
			preparedStmt.setDouble(7, objF.getJuro());

			// executa o sql
			preparedStmt.execute();

			conn.close();
		} catch (Exception e) {
			System.err.println("Ocorreu um erro ao inserir!");
			System.err.println(e.getMessage());
		}
	}

	@Override
	public void update(Object obj) {
		try {
			Titulo objF = (Titulo) obj;
			// cria o objeto de conexao
			Connection conn = conexao();

			// monta o sql de insert
			String query = " update Titulo set \"idSituacao\" = ?, \"idCliente\" = ?, \"dataCadastro\" = ?, \"dataVencimento\" = ?, \"valorDebito\" = ?, \"juroMes\" = ?, \"juro\" = ? where id = ?";

			// cria os parametros a serem passados no insert
			PreparedStatement preparedStmt = conn.prepareStatement(query);
			preparedStmt.setInt(1, objF.getSituacao().getId());
			preparedStmt.setInt(2, objF.getCliente().getId());
			preparedStmt.setDate(3, new Date(objF.getDataCadastro().getTime()));
			preparedStmt.setDate(4,
					new Date(objF.getDataVencimento().getTime()));
			preparedStmt.setDouble(5, objF.getValorDebito());
			preparedStmt.setDouble(6, objF.getJuroMes());
			preparedStmt.setDouble(7, objF.getJuro());
			preparedStmt.setInt(8, objF.getId());

			// executa o sql
			preparedStmt.execute();

			conn.close();
		} catch (Exception e) {
			System.err.println("Ocorreu um erro ao alterar!");
			System.err.println(e.getMessage());
		}
	}

	@Override
	public void delete(int id) {
		try {
			// cria o objeto de conexao
			Connection conn = conexao();

			// monta o sql de insert
			String query = " delete from Titulo where id = ?";

			// cria os parametros a serem passados no insert
			PreparedStatement preparedStmt = conn.prepareStatement(query);
			preparedStmt.setInt(1, id);

			// executa o sql
			preparedStmt.execute();

			conn.close();
		} catch (Exception e) {
			System.err.println("Ocorreu um erro ao excluir!");
			System.err.println(e.getMessage());
		}
	}

	@Override
	public List<Object> findAllById(int id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void updateAviso(int aviso, int id) {
		// TODO Auto-generated method stub

	}

	@Override
	public List<Object> findClienteAviso() {
		// TODO Auto-generated method stub
		return null;
	}
}
